﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

namespace WebApplication1.Core
{
    /// <summary>
    /// 
    /// </summary>

    public class Tea
    {//真麻烦，还是建议用java写，不然他改了算法，你也要跟着改。你用java写完公开为web服务，然后用.net调用最好。
    //他改了算法你只要重新引用Tea.jar就可以了。
        private int[] KEY = new int[] { //加密解密所用的KEY
		1, 2, 3, 4 };
        private String separatoradd = "0"; //加密字符串分隔符"+"

        private String separatordel = "1"; //加密字符串分隔符"-"
        //加密
        private sbyte[] encrypt(
            sbyte[] content,
            int offset,
            int[] key,
            int times)
        { //times为加密轮数
            int[] tempint = byteToint(content, offset);
            int y = tempint[0], z = tempint[1], sum = 0, i;
            //int  delta = 0x9e3779b9; //这是算法标准给的值
            int delta = -1640531527;
            int a = key[0], b = key[1], c = key[2], d = key[3];

            for (i = 0; i < times; i++)
            {
                sum += delta;
                y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
            }
            tempint[0] = y;
            tempint[1] = z;
            return intToByte(tempint, 0);
        }
        //解密
        private sbyte[] decrypt(
            sbyte[] encryptContent,
            int offset,
            int[] key,
            int times)
        {
            int[] tempint = byteToint(encryptContent, offset);
            int y = tempint[0], z = tempint[1], i;
            //int sum = 0xC6EF3720//
            //int delta = 0x9e3779b9; //这是算法标准给的值
            int delta = -1640531527;
            int sum = -957401312;

            int a = key[0], b = key[1], c = key[2], d = key[3];

            for (i = 0; i < times; i++)
            {
                z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
                y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
                sum -= delta;
            }
            tempint[0] = y;
            tempint[1] = z;

            return intToByte(tempint, 0);
        }
        //byte[]型数据转成int[]型数据
        private int[] byteToint(sbyte[] content, int offset)
        {

            int[] result = new int[content.Length >> 2];
            for (int  i = 0, j = offset; j < content.Length; i++, j += 4)
            {
                result[i] =
                    transform(content[j + 3]) | transform(content[j + 2])
                        << 8 | transform(content[j + 1])
                        << 16 | (int)content[j]
                        << 24;
            }
            return result;

        }
        //int[]型数据转成byte[]型数据
        private sbyte[] intToByte(int[] content, int offset)
        {
            sbyte[] result = new sbyte[content.Length << 2];
            for (int  i = 0, j = offset; j < result.Length; i++, j += 4)
            {
                result[j + 3] = (sbyte)(content[i] & 0xff);
                result[j + 2] = (sbyte)((content[i] >> 8) & 0xff);
                result[j + 1] = (sbyte)((content[i] >> 16) & 0xff);
                result[j] = (sbyte)((content[i] >> 24) & 0xff);
            }
            return result;
        }
        //若某字节被解释成负的则需将其转成无符号正数
        private int transform(sbyte temp)
        {
            int tempint = (int)temp;
            if (tempint < 0)
            {
                tempint += 256;
            }
            return tempint;
        }
        //	通过TEA算法加密信息
        public String encryptByTea(String info)
        {
            sbyte[] temp = Encoding.UTF8.GetBytes(info).Select(i => (sbyte)i).ToArray();
            
            int n =(int)( 8 - temp.Length % 8); //若temp的位数不足8的倍数,需要填充的位数
            sbyte[] encryptStr = new sbyte[temp.Length + n];
            encryptStr[0] = (sbyte)n;
            Array.Copy(temp,0, encryptStr, n, temp.Length);
            //for (int i = 0; i < temp.Length; i++)
            //{
            //    encryptStr[i] =(sbyte) temp[n + i];
            //}
            sbyte[] result = new sbyte[encryptStr.Length];
            for (int offset = 0; offset < result.Length; offset += 8)
            {
                sbyte[] tempEncrpt = encrypt(encryptStr, offset, KEY, 32);
                Array.Copy(tempEncrpt, 0, result, offset, 8);
                //Vegeta
            }
            String tmp = encryptTwo(result);
            //		for (int i = 0; i < result.length; i++) {
            //			tmp = tmp + result[i] + this.separator;
            //		}
            return tmp;
        }

        private String encryptTwo(sbyte[] source)
        {
            String all = "";
            for (int i = 0; i < source.Length; i++)
            {
                String tmp = this.separatoradd;
                int s = source[i];
                if (s < 0)
                {
                    s = ~s + 1;
                    tmp = this.separatordel;
                }
                String res = s.ToString("X2");
                if (res.Length == 1)
                    res = "0" + res;
                all = all + res + tmp;
            }
            return all;
        }

        public sbyte[] decryptTwo(String res)
        {
            int k = 0;
            sbyte[] result = new sbyte[res.Length / 3];
            for (int i = 0, j = 3; i < res.Length; i = i + 3, j = i + 3)
            {
                String tmp = res.Substring((int)i, 3);
                if (this.separatoradd.Substring(0) == tmp.Substring(2))
                    result[k++] = SByte.Parse(tmp.Substring(0, 2),System.Globalization.NumberStyles.HexNumber);
                else if (this.separatordel.Substring(0) == tmp.Substring(2))
                    result[k++] =(sbyte)(-SByte.Parse(tmp.Substring(0, 2), System.Globalization.NumberStyles.HexNumber));
                    
            }
            return result;
        }
        //	  通过TEA算法解密信息
        public String decryptByTea(String info)
        {
            sbyte[] secretInfo = this.decryptTwo(info);
            sbyte[] decryptStr = null;
            sbyte[] tempDecrypt = new sbyte[secretInfo.Length];
            for (int offset = 0; offset < secretInfo.Length; offset += 8)
            {
                decryptStr = decrypt(secretInfo, offset, KEY, 32);
                Array.Copy(decryptStr, 0, tempDecrypt, offset, 8);
                
            }
            int n = tempDecrypt[0];
           // return new String((char[])tempDecrypt,(int) n, ((int)decryptStr.Length - n));

            //var s = "";
            //for (int i = n; i < tempDecrypt.Length; i++)
            //{
            //    s += Convert.ToString(tempDecrypt[i]);
            //}
            var s = tempDecrypt.Select(i => (byte)i).ToArray();
            return Encoding.UTF8.GetString(s, (int)n, (int)(s.Length - n));
            //return s;
        }

        public static void Test() {
		Tea tea = new Tea();
		String src ="abcd1234";
		String tmp = tea.encryptByTea(src);
		String result = tea.decryptByTea("2700304515a02c16411f06e14f17b14e16401c01c0591390");
		Console.Write("原数据：");
		Console.WriteLine(src);
		Console.Write("加密后的数据：");
		Console.WriteLine(tmp);
		Console.Write("解密后的数据：");
        Console.WriteLine(result);
	}
    }
}